Know every vulnerabilitybefore it knows you.
DevGuard continuously monitors your dependencies and alerts you when CVEs like this one affect your stack — with real-time threat intelligence built for developers.
GHSA-rh9c-rqvg-f7pr
Summary
Every Linuxfabrik check plugin that supports the shared --test argument (routed through lib.lftest.test()) will, when --test is supplied, treat the first CSV element as a filesystem path and read its full contents as the plugin's simulated STDOUT — running as root when the plugin is invoked through the shipped nagios/icinga sudoers allowlist. --test is a live production argument (centrally mapped to argparse.SUPPRESS, so it is hidden from --help but still accepted on the command line), not a build-time-only gate. This yields an arbitrary root file-read primitive (full disclosure on deb-updates; filtered disclosure / existence-and-readability oracle on ~22 other whitelisted plugins), i.e. local privilege escalation from the nagios account to root.
Root Cause
lib.lftest.test(args)(lftest.pylines 659-664):stdout = args[0];if stdout and os.path.isfile(stdout): _, stdout = disk.read_file(stdout). Element[1] (stderr channel) is read the same way. There is no path confinement on the supplied path.check-plugins/deb-updates/deb-updates:--testis registered withtype=lib.args.csv(lines 78-82). When supplied, control flows tostdout, _, retc = lib.lftest.test(args.TEST)(line 143), bypassing the apt path (if args.TEST is None:at 121). Each returned line is stored as apackagerow and, under the default--query='1'(WHERE 1, matches all rows), every row is printed via'\n* '.join([row['package'] ...])→lib.base.oao(...).- The same
--test/lib.lftest.test()mechanism exists identically on ~22 whitelisted plugins (e.g.docker-info), each performing a rootopen()/read of the attacker-named path. Disclosure degree varies by each plugin's downstream parser: full (deb-updates), filtered (docker-infoechoes lines containingwarning:/error:;openvpn-client-listechoesCLIENT_LISTlines), or existence/readability oracle (JSON parsers).
Impact
An attacker controlling the low-privilege nagios/icinga account (the documented threat model for the shipped sudoers file — same precondition as CVE-2026-52817) obtains the full contents of any root-readable file via deb-updates (e.g. /etc/shadow, /root/.ssh/id_*, TLS keys, cloud credentials), plus a fleet-wide root file existence/readability oracle and filtered content leak via the other plugins → local privilege escalation to root.
Proof of Concept
Full disclosure (deb-updates):
sudo /usr/lib64/nagios/plugins/deb-updates --test=/etc/shadow,,0
Filtered disclosure / oracle (docker-info, target routed to the stderr channel that gets echoed):
sudo /usr/lib64/nagios/plugins/docker-info --test="dummy,/etc/shadow,0"
Attack Chain
- Entry:
sudo /usr/lib64/nagios/plugins/deb-updates --test=/etc/shadow,,0- Action: the nagios user invokes the whitelisted plugin as root with a
--testCSV whose element[0] is the target path and retc=0. - Guard: sudoers (Debian.sudoers:3) lists the binary only;
--testis not gated to test builds. - Bypass proof: CONTRIBUTING.md documents
--testas centrally mapped toargparse.SUPPRESS— hidden from--helpbut still accepted on the command line;lib.args.csvsplits/etc/shadow,,0into['/etc/shadow','','0'].
- Action: the nagios user invokes the whitelisted plugin as root with a
- Sink:
lib.lftest.test(args.TEST)(deb-updates:143) reads element[0] as a file, as root.- Guard: none — no path confinement on element[0].
- Bypass proof (from lib source):
lftest.py:661-664:stdout = args[0]; if stdout and os.path.isfile(stdout): _, stdout = disk.read_file(stdout)— element[0], if it exists on disk, is opened and its contents returned as stdout.retc=0(element[2]) so there is no earlycu()abort.
- Store + query: each line →
lib.db_sqlite.insert(conn, {'package': item}, ...); defaultQUERY='1'→SELECT * FROM deb_updates WHERE 1.- Guard:
--only-criticalor a restrictive--querywould filter, but both default to permissive (ONLY_CRITICAL=False,QUERY='1'). - Bypass proof: attacker passes neither → all rows selected.
- Guard:
- Disclosure:
msg += '\n* '.join([row['package'] for row in result])→lib.base.oao(...)→ stdout.- Guard: none.
- Bypass proof: with
len(result) > 0the branch prints every row (every file line).
- Impact: full contents of any root-readable file disclosed to the nagios user → root. On the ~22 other
--testplugins the same primitive yields a filtered leak / universal root file existence-and-readability oracle.
Bypass Evidence
lib.lftest.test()file-read behavior verified directly from linuxfabrik-lib source (lftest.py:659-664,disk.read_file(stdout)whenos.path.isfile(stdout)).--testregistration (type=lib.args.csv) and thestdout, _, retc = lib.lftest.test(args.TEST)call verified on the latest release tag v6.0.0 atcheck-plugins/deb-updates/deb-updates:143(GitHub contents API); defaultQUERY='1'confirmed.- No path-confinement guard exists on the
--testpath element in either the plugin orlib.lftest.
Affected Versions
<= 6.0.0 (latest release; --test/lib.lftest.test() flow present on tag v6.0.0). Not covered by any existing advisory (none reference --test or arbitrary file read).
Suggested Fix
Compile --test out of production builds (or gate it behind an explicit build/dev flag so it is not accepted at runtime), OR confine the --test path element(s) to a dedicated fixtures directory via realpath() + containment check before disk.read_file(). As defense-in-depth, constrain the sudoers entries to specific argument values so --test cannot be supplied to a root-run plugin.
Reported by zx (Jace)
The vulnerability requires local access to the device to be exploited. It is easy for an attacker to exploit this vulnerability. An attacker needs basic access or low-level privileges. No user interaction is needed for the attacker to exploit this vulnerability. The impact is confined to the system where the vulnerability exists. There is a high impact on the confidentiality of the information.
Exploitation attempts have been detected. Elevated vigilance and prompt remediation are advised.
The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.
We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database.
Browse More
Continuously monitor your dependencies and get alerted when vulnerabilities like this one affect your stack.
Checkout DevGuard