
Script to check if system are vulnable to cve-2026-23111
CVE-2026-23111 is a Linux kernel vulnerability in nf_tables that can be exploited for local privilege escalation by an unprivileged user on systems where user namespaces and nftables are available.[1][2] Public vendor and government advisories describe it as a local issue affecting Linux distributions and emphasize patching as the primary fix.[3][4]
This repository contains a defensive validation script designed to help assess whether a host exposes the technical conditions associated with this CVE without delivering a privilege-escalation exploit. It checks for relevant kernel and runtime conditions, optionally loads the nf_tables module for full functional testing, attempts a controlled non-privileged validation path using unshare and nft, collects local diagnostic traces, and classifies the host into operational verdicts such as likely safe, blocked by local policy, or exposed path available.[1][5]
According to the NVD, CVE-2026-23111 is a Linux kernel nf_tables vulnerability resolved as a logic bug fix in netfilter and is exploitable for local privilege escalation from an unprivileged user through user namespaces and nftables on affected configurations.[1] Ubuntu’s security notice describes the same high-level exploitation path and tracks affected and fixed package states by release.[2]
Red Hat states that a local low-privileged user may exploit the issue to cause denial of service or potentially achieve privilege escalation, and it documents a mitigation path based on preventing the nf_tables module from loading when that is operationally acceptable.[3] National-level guidance from the Canadian Centre for Cyber Security also points affected organizations to vendor updates and mentions initramfs regeneration when module-blocking mitigations are used.[4]
The script is intended for defensive exposure assessment, not exploitation. It is designed to:
CONFIG_USER_NS and CONFIG_NF_TABLES appear to be present.[1]kernel.unprivileged_userns_clone and user.max_user_namespaces to estimate whether unprivileged user namespaces are available.install nf_tables /bin/false) or a weak blacklist is in place for the nf_tables module./proc/kallsyms for the vulnerable symbol (nft_map_catchall_activate) vs. the post-patch symbol (nft_catchall_set_activate) before any module interaction.nf_tables via modprobe when --allow-load-module is specified (see below), and unload it automatically at exit.The script stores logs in a child directory of the script directory and removes them by default unless --keep-logs is used.
By default the script never loads nf_tables. If the module is not already loaded when the script starts, all functional nft tests are skipped and the verdict is derived solely from kernel version, kallsyms fingerprint, modprobe configuration, RPM changelog, and sysctl/LSM policy evidence.
This conservative default avoids unintentionally expanding the attack surface on production hosts. To enable full functional testing on a controlled or instrumented system, use --allow-load-module as root (see below).
# Default — no module loading, policy-evidence-only verdict
./check_cve_2026_23111.sh
./check_cve_2026_23111.sh --color
./check_cve_2026_23111.sh --keep-logs
./check_cve_2026_23111.sh --color --keep-logs
# Full functional test — loads (and unloads) nf_tables, requires root
sudo ./check_cve_2026_23111.sh --allow-load-module
sudo ./check_cve_2026_23111.sh --allow-load-module --color --keep-logs
--allow-load-moduleUse --allow-load-module when you need the highest-confidence verdict on an isolated, non-production, or purpose-built test VM. Typical scenarios:
Do not use --allow-load-module on production hosts where nf_tables is intentionally blocked or where loading it would violate a hardening policy.
--allow-load-moduleBefore attempting to load the module, the script enforces the following checks and exits with an error if any of them fail:
install nf_tables /bin/false) must not be present in /etc/modprobe.d/.modprobe must be available on the system.root (uid 0).If the module is successfully loaded by the script, modprobe -r nf_tables is called at exit via the cleanup() trap, regardless of how the script terminates (success, error, or CTRL+C).
The script uses operational verdicts rather than exploit outcomes:
These verdicts are intended to support patch prioritization and defensive triage, not to replace vendor package status validation.
The script maps the running kernel against documented upstream fix points:
The primary recommended action is to install the vendor-fixed kernel update and reboot into the corrected kernel.[2][3][4] Because exploitation depends on local kernel attack surface, additional hardening can reduce exposure while patching is being scheduled or validated.[5][6]
nf_tables loading if the system does not require nftables functionality and the change has been validated for operational impact.[3][4]CAP_NET_ADMIN, and reduce the number of accounts that can manipulate firewall state.[5]Restrict unprivileged user namespaces:
echo 'kernel.unprivileged_userns_clone=0' > /etc/sysctl.d/99-cve-2026-23111.conf
echo 'user.max_user_namespaces=0' >> /etc/sysctl.d/99-cve-2026-23111.conf
sysctl --load /etc/sysctl.d/99-cve-2026-23111.conf
Block nf_tables module loading when operationally safe:
echo 'install nf_tables /bin/false' > /etc/modprobe.d/disable-nf_tables.conf
rmmod nf_tables 2>/dev/null || true
If a module-loading mitigation is used, some guidance recommends regenerating initramfs so the blocked module is not loaded during early boot.[4]
Ubuntu documents AppArmor-based restrictions for unprivileged user namespaces as a way to reduce attack surface rather than as a complete substitute for kernel fixes.[6] A host may appear less exposed in runtime testing because the attack path is blocked locally, while the long-term remediation still requires installing the vendor-fixed kernel package.[2][6] The script validates AppArmor restriction effectiveness by attempting an actual unshare --user invocation and checking whether CAP_NET_ADMIN inside a user+net namespace is functional.
Red Hat explicitly lists preventing the nf_tables module from being loaded as a mitigation for CVE-2026-23111 when that change is appropriate for the environment.[3] The script detects this configuration via check_modprobe_deny() and distinguishes between a hard deny (install nf_tables /bin/false, which blocks on-demand loading) and a weak blacklist (which does not). On RHEL-family systems the script also inspects the running kernel’s RPM changelog for a CVE-2026-23111 backport entry, enabling vendor-confirmed verdict independent of the upstream version number.
This README and the companion script are intended for defensive validation, inventorying, and mitigation planning. They do not replace vendor guidance, package-level verification, or standard patch-management processes, and they should not be used as a substitute for applying the official fixes described in the linked advisories.[2][3][4]
A repository for learning, testing, and researching cybersecurity concepts in controlled environments.
This repository is for educational and authorized security research only.
It is designed to help users learn about:
Use this repository only in environments where you have permission, such as:
Unauthorized or illegal use is strictly prohibited.
The author and contributors are not responsible for any damage, misuse, legal issues, or losses caused by this project.
By using this repository, you agree that:
This project is intended for:
Please follow responsible disclosure practices and comply with all applicable laws.
For responsible disclosure or collaboration, contact the repository maintainer through GitHub.
unshare -U -n --map-root-user + nft validation step when the module is loaded, and record stdout, stderr, and recent kernel logs.unshare --user actually creates a namespace and that CAP_NET_ADMIN is functional inside it, to confirm whether AppArmor or SELinux restrictions are truly effective.| Option | Description |
|---|
--allow-load-module | Authorize the script to load nf_tables via modprobe if the module is not already loaded. Enables the full nft catchall path exerciser and the CAP_NET_ADMIN effectiveness test. The module is unloaded automatically at exit. Requires root. Refused if a hard modprobe deny is already in place. Only use on non-production or instrumented systems. |
--color | Enable colorized stdout output when the terminal supports it. |
--keep-logs | Keep logs and traces under the script directory instead of deleting them at exit. |
--help | Print usage information and exit. |
| Verdict | Meaning |
|---|
not-affected | Kernel version is below 5.13; the catchall element feature was not yet introduced and the vulnerable code path is absent. |
likely-patched-vendor-confirmed | CVE-2026-23111 was found in the vendor kernel RPM changelog, confirming a backported fix regardless of upstream version. |
likely-patched-upstream-confirmed | Kernel version is in the patched upstream range and the functional nft test returned non-zero with no kernel signal — strongest static + dynamic evidence of a safe state. |
likely-patched-upstream | Kernel version is in a patched upstream range but functional test was not run (module absent, or inconclusive). Vendor advisory status should still be checked. |
likely-safe-or-patched | No exploitable path was confirmed by the script; cause is ambiguous between a patched kernel, absent vulnerable code, or implicit local block. |
blocked-by-local-policy | The tested path appears blocked by AppArmor, SELinux, user namespace restrictions, or a modprobe deny.[6] Policy blocks are not a substitute for the vendor fix. |
exposed-path-available | The host exposes a userns + nftables path compatible with the documented exploitation prerequisites.[1][5] |
strong-signal-lab-confirmation | A kernel log signal consistent with nf_tables-related memory corruption was observed. Confirm only in a disposable, instrumented lab. |
prerequisites-missing | Required diagnostic tools (unshare, nft) are missing; no meaningful runtime validation was completed. |
| Branch | Fixed at | Upstream commit |
|---|
| 6.13.x+ | ≥ 6.13.1 | f41c5d1 |
| 6.12.x | ≥ 6.12.12 | 8c760ba |
| 6.6.x | ≥ 6.6.75 | b9b6573 |
| 6.1.x | ≥ 6.1.128 | 8b68a45 |
| 6.2–6.5, 6.7–6.11 | EOL upstream | distro backport only |
| 5.15.x | distro-dependent | Amazon Linux: ALAS2KERNEL-5.15-2026-098 |
| 5.10.x | distro-dependent | Amazon Linux 2: pending as of 2026-03 |
| 5.4.x | distro-dependent | Amazon Linux 2: pending as of 2026-03 |
| 5.13–5.14 | EOL upstream | distro backport only |
| < 5.13 | not affected | catchall feature not present |