A buffer overflow you have to hand-feed to yourself at an interactive prompt
xmlcatalog --shell is an interactive REPL bundled with libxml2 for editing XML catalog files. Inside its usershell() function, the parser copies input lines into fixed-size stack buffers (command, arg, argv) without bounds checks. Feed it a very long line at the interactive prompt and you smash the stack of the xmlcatalog process. Affects all libxml2 versions through 2.15.3; fixed in commit c2e233fc, expected to ship in the next libxml2 point release.
Vendor severity is HIGH (7.8) mechanically because CVSS math sees AV:L/PR:N/UI:R/C:H/I:H/A:H and treats "local code execution" as high impact. But look at the attack surface: the vulnerable code is a debugging shell that a human types into, not a library entry point, not a parser reachable from xmlReadFile, not something a service loads. The libxml2 maintainers publicly disputed the CVE and classified this as a bug, not a vulnerability — and they are correct. Real-world exploitability requires the attacker to already be sitting at a shell as the target user, at which point they don't need a stack overflow in xmlcatalog.
3 steps from start to impact.
Attacker delivers a crafted input line to xmlcatalog --shell
xmlcatalog --shell and paste, type, or pipe an oversized line into the interactive prompt. Weaponization would be a text file or clipboard payload staged via social engineering (cat evil.txt | xmlcatalog --shell somefile.xml). No public PoC binary exists beyond the researchers' proof.- Victim runs xmlcatalog with the --shell flag interactively
- Attacker can influence the input stream (stdin, pasted content, or a script the victim executes)
- xmlcatalog --shell is a developer/packager debugging tool — not run in production or by end users
- No service, daemon, or web app invokes --shell mode
- Attacker already needs a channel to feed input, which usually implies prior code execution or local access
Stack buffers in usershell() overflow
command, arg, and argv buffers are fixed-size on the stack. Input exceeding their length overwrites adjacent frame data including the saved return address. On modern glibc builds with -fstack-protector-strong, this trips the stack canary and aborts.- libxml2 ≤ 2.15.3
- xmlcatalog binary built without stack canaries or with weak toolchain hardening
- Every mainstream distro compiles libxml2 with
-fstack-protector-strong— canary abort turns RCE into a crash - ASLR + PIE randomize the return-address target
- No heap grooming primitive; overflow is purely stack-linear
Best-case outcome: code execution as the invoking user
- Successful ROP or shellcode delivery inside xmlcatalog's process
- No privilege boundary is crossed — same UID as the interactive user
- xmlcatalog is not setuid anywhere in Debian, Ubuntu, RHEL, SUSE, Alpine, or Arch
grep -rEn 'xmlcatalog.*(-|--)shell' /etc /opt /usr/local /var /home and check CI pipelines. If any automated workflow pipes untrusted input into xmlcatalog --shell, refactor it — that is the only realistic exploitation scenario and it is a design flaw regardless of the CVE.checksec --file=$(which xmlcatalog) on a sample host from each distro image. Every mainstream distro passes; custom yocto/buildroot/Alpine musl images may not. This is one-time hygiene, not a per-CVE task.- WAF rules or network ACLs — the vuln is local, no network vector exists.
- Removing libxml2 — libxml2 is a dependency of GNOME, systemd tooling, package managers, XML parsers across the OS. You cannot remove it and the library itself is not vulnerable.
- Disabling xmlcatalog binary (chmod 000) — will break legitimate packager/developer workflows for no security gain, since nobody exploits this at scale.
The supporting signals.
| In-the-wild exploitation | None observed. Not tracked by CISA KEV, Mandiant, or Unit 42. |
|---|---|
| Public PoC | No public exploit code. Researcher writeup at CERT Polska describes the crash primitive only. |
| EPSS | 0.00148 (≈ 0.15 percentile) — one of the lowest active-exploitation forecasts in the CVE corpus. |
| KEV status | Not listed. Would not qualify under CISA criteria (no in-the-wild, no remote reachability). |
| CVSS vector | AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — local, requires user interaction. The high impact score comes from theoretical RCE, not real reachability. |
| Affected versions | libxml2 ≤ 2.15.3 (all branches). Only the xmlcatalog binary in --shell mode is affected; the libxml2 library itself is unaffected. |
| Fixed version | Upstream commit c2e233fc. Distro backports pending: watch Debian DSA, RHSA, USN trackers. |
| Exposure telemetry | Not applicable — xmlcatalog --shell is an interactive local tool, not a network service. GreyNoise/Shodan/Censys not relevant. |
| Disclosure | 2026-06-29 via CERT Polska coordinated disclosure. |
| Discovered by | Michal Majchrowicz and Marcin Wyczechowski of AFINE. Vendor (GNOME libxml2 maintainers) publicly disputed the vulnerability classification and calls it a bug. |
Sources.
- CERT Polska advisory (CVE-2026-11979)
- TheWindowsUpdate summary of CVE-2026-11979
- GNOME libxml2 GitLab issue tracker (related shell.c bugs)
- Red Hat Security Advisory tracker (libxml2)
- Debian libxml2 source-package security tracker
- IBM AIX/VIOS libxml2 bulletin (historic advisory format)
- CVE Details — libxml2 vulnerability history
Why this verdict
- Vendor disputes it's a vulnerability at all. The libxml2 maintainers classified this as a bug and not a security issue — a rare and telling signal from an upstream that normally cooperates with CVE assignment.
- Attack vector is local + UI-required + no privilege boundary crossed. The user who runs
xmlcatalogis the same user the attacker ends up executing as. There is no LPE, no sandbox escape, no service compromise. - Reachability is effectively zero on production hosts.
xmlcatalog --shellis a developer/packager tool. No web server, no CI runner, no daemon, no SUID binary invokes it. Grep your fleet for any process ever spawning it — you will find none. - Modern toolchain hardening neutralizes the RCE. All mainstream distros ship libxml2 built with
-fstack-protector-strong, PIE, ASLR, and RELRO. The overflow becomes a canary-aborted crash, not code execution. - Role multiplier: none applicable. libxml2 is deployed on essentially every Linux host, but the vulnerable component (
xmlcatalog --shell) is NOT reachable in any high-value role — not on hypervisors, not on domain controllers, not on CAs, not on backup servers. The library-level parsing paths are unaffected, so the deployment-role floor does not lift this above LOW. - EPSS 0.00148 and no PoC. Forecasted exploitation probability is in the bottom fraction of a percent, matching the reachability analysis.
Why not higher?
MEDIUM would require some plausible mass-exploitation or automation path, or a scenario where a non-interactive process invokes xmlcatalog --shell with attacker-controlled stdin. Neither exists in any real deployment we can find, and the vendor themselves refused to call this a vulnerability.
Why not lower?
IGNORE is inappropriate because the code fix is real, distros will ship backports, and a stack overflow that survives compiler hardening on some non-standard build (e.g., embedded, static-linked, canary-disabled) could theoretically yield local code execution in the invoking user's UID. It belongs in the standard patch cycle, just not the emergency lane.
Crowdsourced verification payload.
Run on the target Linux host as any user (no privileges required). Invoke as ./check_cve_2026_11979.sh. Compares the installed libxml2 version against the 2.15.3 fixed threshold and reports VULNERABLE / PATCHED / UNKNOWN. Also flags weak toolchain hardening on the xmlcatalog binary.
#!/usr/bin/env bash
# check_cve_2026_11979.sh
# Detects vulnerable libxml2 (<= 2.15.3) affecting xmlcatalog --shell mode.
# Exit codes: 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN.
set -u
FIXED_AFTER="2.15.3"
get_version() {
if command -v xml2-config >/dev/null 2>&1; then
xml2-config --version 2>/dev/null
return
fi
if command -v xmlcatalog >/dev/null 2>&1; then
xmlcatalog --version 2>&1 | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -1
return
fi
if command -v dpkg-query >/dev/null 2>&1; then
dpkg-query -W -f='${Version}\n' libxml2 2>/dev/null | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -1
return
fi
if command -v rpm >/dev/null 2>&1; then
rpm -q --qf '%{VERSION}\n' libxml2 2>/dev/null | head -1
return
fi
}
ver_le() {
# returns 0 if $1 <= $2
[ "$1" = "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -1)" ]
}
VER=$(get_version | tr -d '[:space:]')
if [ -z "${VER:-}" ]; then
echo "UNKNOWN: libxml2 not detected on this host"
exit 2
fi
echo "Detected libxml2 version: $VER"
if ver_le "$VER" "$FIXED_AFTER"; then
echo "VULNERABLE: libxml2 $VER <= $FIXED_AFTER (CVE-2026-11979)"
# Bonus: check if xmlcatalog is hardened; hardened builds significantly reduce risk
if command -v checksec >/dev/null 2>&1 && command -v xmlcatalog >/dev/null 2>&1; then
echo "--- xmlcatalog hardening ---"
checksec --file="$(command -v xmlcatalog)" 2>/dev/null || true
fi
exit 1
fi
echo "PATCHED: libxml2 $VER > $FIXED_AFTER"
exit 0