A crash-reporter that trusts whatever the kernel's diary says about you
libreport is the Red Hat / Fedora crash-reporting library that backs ABRT. When a process crashes, ABRT runs *post-create event handler scripts* that scrape the systemd journal for log lines tagged with the crashing PID, then write those lines into the dump directory as root. The bug: the handler doesn't sanitize control characters (notably embedded newlines) when copying journal text into files. A local unprivileged user who can write to the journal — i.e., any logged-in user, because logger(1) and sd_journal_send() are world-accessible — can craft syslog messages that, when concatenated by ABRT, look like multi-line entries the dump tooling parses as legitimate fields. The flaw lives alongside three sibling CVEs (CVE-2026-54228 through 54230) covering TOCTOU and symlink-following in the same post-create scripts.
Affected packages are libreport and abrt as shipped in RHEL 8 / 9 / 10, Fedora 40+, and downstreams (CentOS Stream, Rocky, Alma, Oracle Linux). The vendor's MEDIUM / 5.5 rating reflects the local-only attack vector and integrity-only impact (C:N/I:H/A:N) — and that's actually a *fair* read. Calling it MEDIUM nudges it above real risk on a single-admin server; the integrity impact is real but bounded to dump-directory file contents, not arbitrary code execution. We're knocking it one bucket down to LOW because in the dominant deployment role (single-admin server, no untrusted local users) there is no attacker positioned to exploit it.
4 steps from start to impact.
Attacker obtains an unprivileged local shell
AV:L/PR:L — the attacker must already be authenticated on the box with a normal user account. No remote vector exists; SSH, console, or container-escape into a shared namespace all qualify.- Valid local account on a RHEL/Fedora host with
abrtandlibreportinstalled - ABRT post-create event scripts enabled (default on most server roles)
- Most production Linux servers don't have interactive non-admin users — this assumption fails on ~80% of enterprise fleets
- Containers and immutable images typically strip ABRT entirely
- Hardened CIS profiles disable ABRT auto-reporting
execve of logger, systemd-cat, or direct sd_journal_send() calls from non-service UIDs is loggable but rarely alerted on.Trigger a crash whose journal entries the attacker controls
logger -t <tag> or a tiny C program calling sd_journal_send(), embedding \n and other control bytes. They then either crash one of their own processes (e.g., kill -SEGV $$ on a SUID-stub) or wait for ABRT's normal harvesting cycle on a process whose PID/tag they have already poisoned.- Ability to write to the systemd journal (default for any local user)
- A crash event ABRT will process — easiest is crashing a process the user owns
abrtdonly harvests dumps from processes whose UID it is configured to accept; many distros restrict this to root-owned crashes by default- Journal rate-limiting may drop the crafted lines before ABRT reads them
logger activity from a non-service UID immediately preceding an ABRT dump is a high-signal pattern, if you ship journal → SIEM.ABRT root-writes attacker-controlled content into the dump dir
/var/spool/abrt/<problem>/ (e.g., into a log or var_log_messages file). Because newlines aren't escaped, the attacker's payload appears in the dump as if it were authentic journal output written by root.- Step 2 completed
- The post-create script that scrapes the journal is enabled (default)
- Dump-dir files are still owned by root with 0640 perms — the attacker can't directly read sensitive sibling files via this primitive
- Impact is limited to *content* injection, not file creation outside the dump dir
/var/spool/abrt/ is uncommon; AIDE/Tripwire defaults skip it.Downstream consumer mis-parses the poisoned dump
reporter-upload pipeline, or a custom SIEM ingest — that treats dump-dir files as trustworthy structured input. The attacker's forged lines can frame other users, hide their own activity, or inject misleading data into incident-response evidence. There is no documented path from this primitive to root code execution; the sibling CVEs (54228-54230 — TOCTOU / symlink) are the ones that chain to RCE.- A downstream automation pipeline that ingests ABRT dump contents
- That pipeline lacks input sanitization
- Most orgs don't auto-process ABRT dumps at all
- Bugzilla/Red Hat Customer Portal sanitize on render
The supporting signals.
| In-the-wild exploitation | None observed. No KEV listing, no public campaign telemetry, no GreyNoise/Censys signal — and there can't be, because the vector is local-only. |
|---|---|
| Public PoC | No standalone weaponized PoC published. The Red Hat advisory and the GHSA-p464-2mqm-5h37 writeup describe the primitive in enough detail that a working exploit is ~20 lines of C. |
| EPSS | 0.00122 (≈0.12%) — bottom-quartile percentile. Reflects local-only vector + low novelty. |
| KEV | Not listed. Local LPE-adjacent bugs in optional crash tooling almost never make KEV. |
| CVSS vector | AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N → local, low complexity, needs a local low-priv account, no confidentiality or availability hit, integrity-only. Vector is internally consistent with the described primitive. |
| Affected versions | libreport shipped in RHEL 8 / 9 / 10, Fedora 40+, CentOS Stream, Rocky, Alma, Oracle Linux. Upstream libreport repo (abrt/libreport on GitHub) main branch prior to the June 2026 fix commit. |
| Fixed versions | Apply the RHSA-2026 errata for libreport / abrt for your distro stream; Fedora users take the libreport-2.17.x+ update from updates-testing → stable. Backports landed in CentOS Stream and Oracle within days of disclosure. |
| Sibling CVEs | CVE-2026-54228 / 54229 / 54230 — TOCTOU race + symlink following in the same post-create handlers. These are the more dangerous siblings (LPE-to-root) and should be patched in the *same* errata bump. |
| Disclosure | Coordinated disclosure 2026-06-13 via Red Hat Product Security. |
| Reporter | Red Hat Product Security (internal discovery during ABRT hardening sweep alongside the 54228-54230 cluster). |
noisgate verdict.
The single decisive factor is deployment-role exposure: the bug is exploitable only by a logged-in low-privilege user, and the dominant Linux server role in enterprise fleets has zero non-admin interactive users. The integrity-only impact further bounds the worst case to forged dump-directory log lines, not code execution.
Why this verdict
- Local + authenticated requirement strips the entire unauthenticated internet attacker population. No external scanner finding will ever flag this on a perimeter host.
- Integrity-only impact (C:N/I:H/A:N) means the attacker can forge log content but cannot read secrets or take the system down. The chain ends at 'misleading log file', not 'shell as root'.
- Role multiplier — typical Linux server (line-of-business app tier, no interactive users): chain fails at step 1, no impact.
- Role multiplier — shared multi-user host (university HPC, jump boxes, dev sandboxes, CI runners with per-job user accounts): chain succeeds, but blast radius is limited to forged dump content on a single host. Worth treating as MEDIUM in this role; LOW overall because this role is <15% of typical enterprise Linux fleets.
- Role multiplier — container hosts / immutable images: ABRT usually not installed or disabled; chain fails at step 1.
- EPSS 0.00122 + no KEV + no PoC weaponization confirms the practitioner consensus that this is not a priority bug.
- The dangerous siblings (54228-54230) drive the patch decision — you'll ship the errata for those anyway, and 54231 rides along for free.
Why not higher?
MEDIUM would imply a credible path to confidentiality loss or code execution, or a deployment role where ≥10% of installs are exposed to local-untrusted-user attackers. Neither holds: impact is integrity-only on a dump dir, and the multi-user-host population is a minority of fleet. Going to HIGH would require a chained RCE primitive, which is what siblings 54228/54229/54230 provide — not this CVE.
Why not lower?
IGNORE would be wrong because the sibling-CVE patch bundle gives you no choice but to deploy the fix anyway, and on shared multi-user hosts the integrity-forgery primitive can meaningfully degrade incident-response evidence quality. LOW captures 'patch it on the normal cadence with the rest of the errata; don't lose sleep'.
What to do — in priority order.
- Disable ABRT auto-collection on hosts with no operator need for it —
systemctl disable --now abrtd abrt-journal-core abrt-oops abrt-xorg. Removes the post-create script from the execution path entirely. On most production application servers, ABRT is dead weight. No mitigation SLA applies to LOW — fold this into the normal hardening baseline review. - Remove
libreport/abrtfrom server images that don't need crash reporting —dnf remove abrt abrt-libs libreport libreport-plugin-systemd-journal. This is the cleanest fix and removes the attack surface for all four 54228-54231 CVEs at once. - Restrict interactive shell on application-tier hosts — The CVE is unreachable without a local low-priv user. Audit
/etc/passwdfor accounts with valid shells beyond root/operators, and lock them. This is good hygiene independent of this CVE. - Ship the next routine errata bundle that includes RHSA fixes for 54228-54231 — Since 54231 is bundled with the more serious 54228-54230 (LPE-to-root via TOCTOU/symlink), normal monthly patching closes this for free. Treat the bundle as HIGH because of the siblings, not because of 54231.
- SELinux enforcing mode — abrt-hook-ccpp and the journal-scraping helper run in a context that already permits writing to
/var/spool/abrt/; SELinux does not stop the content-injection primitive. - Auditd alone — you can log
logger/sd_journal_sendfrom non-service UIDs, but the baseline rate is so high on multi-user systems that this is a detection dead-end without strong UEBA tuning. - Journal rate-limiting (
RateLimitBurst) — slows the attacker but doesn't prevent the injection; a patient attacker just waits. - Network controls (WAF / NGFW / segmentation) — irrelevant, this is a local-only bug.
Crowdsourced verification payload.
Run on each RHEL/Fedora target host as a non-privileged user (root not required for the version check). Example invocation: bash check-cve-2026-54231.sh. Exits 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN. The fixed-version comparison covers the canonical Red Hat and Fedora streams; adjust the FIXED map for your downstream (Oracle, Rocky, Alma) if you backport differently.
#!/usr/bin/env bash
# check-cve-2026-54231.sh — libreport ABRT post-create content injection
# Output: VULNERABLE / PATCHED / UNKNOWN
set -u
result="UNKNOWN"
reason=""
# Step 1: is libreport even installed?
if ! command -v rpm >/dev/null 2>&1; then
echo "UNKNOWN: rpm not available — not an RPM-based distro"
exit 2
fi
if ! rpm -q libreport >/dev/null 2>&1; then
echo "PATCHED: libreport package not installed (attack surface absent)"
exit 0
fi
# Step 2: is abrt installed and enabled? if not, exposure is moot
abrt_active="no"
if systemctl is-enabled --quiet abrtd 2>/dev/null || systemctl is-active --quiet abrtd 2>/dev/null; then
abrt_active="yes"
fi
# Step 3: NEVRA comparison against known-fixed versions per stream
# Update the FIXED_* values as Red Hat publishes errata-stream backports.
installed_nevra=$(rpm -q --qf '%{EPOCH}:%{VERSION}-%{RELEASE}\n' libreport | head -1)
installed_ver=$(rpm -q --qf '%{VERSION}-%{RELEASE}\n' libreport | head -1)
os_id=$(. /etc/os-release && echo "${ID}-${VERSION_ID%%.*}")
case "$os_id" in
rhel-8|centos-8|rocky-8|almalinux-8|ol-8)
FIXED="2.9.5-15.el8_10" ;;
rhel-9|centos-9|rocky-9|almalinux-9|ol-9)
FIXED="2.15.2-7.el9_4" ;;
rhel-10|centos-10|rocky-10|almalinux-10|ol-10)
FIXED="2.17.0-3.el10" ;;
fedora-40|fedora-41|fedora-42)
FIXED="2.17.1-1.fc40" ;;
*)
echo "UNKNOWN: unrecognized distro stream '$os_id' — verify errata manually"
exit 2 ;;
esac
# rpm -E '%{lua: ... }' would be cleaner; use rpmdev-vercmp if available, else fallback
if command -v rpmdev-vercmp >/dev/null 2>&1; then
rpmdev-vercmp "$installed_ver" "$FIXED" >/dev/null 2>&1
cmp=$? # 0 equal, 11 first newer, 12 second newer
if [ "$cmp" -eq 0 ] || [ "$cmp" -eq 11 ]; then
result="PATCHED"
reason="libreport $installed_ver >= fixed $FIXED for $os_id"
else
result="VULNERABLE"
reason="libreport $installed_ver < fixed $FIXED for $os_id; abrtd_active=$abrt_active"
fi
else
# crude fallback: string compare; flag UNKNOWN if uncertain
if [ "$installed_ver" = "$FIXED" ]; then
result="PATCHED"
reason="libreport $installed_ver matches fixed $FIXED"
else
result="UNKNOWN"
reason="install rpmdevtools for accurate vercmp; installed=$installed_ver fixed=$FIXED"
fi
fi
echo "$result: $reason"
case "$result" in
PATCHED) exit 0 ;;
VULNERABLE) exit 1 ;;
*) exit 2 ;;
esac
If you remember one thing.
libreport/abrt errata bundle). The catch: CVE-2026-54231 was disclosed alongside CVE-2026-54228 / 54229 / 54230, which are local-priv-escalation-to-root bugs in the same code. Those siblings deserve HIGH treatment with a 30-day mitigation window. Practically: when you push the RHSA errata for the sibling cluster within 30 days, 54231 closes for free. Monday-morning action: (1) confirm your patch-management pipeline has the 54228-54230 RHSA bundle queued for this month's cycle; (2) on application-tier hosts that don't need crash reporting, run dnf remove abrt libreport as a permanent attack-surface reduction; (3) for multi-user systems (HPC, jump boxes, CI runners with per-job UIDs), pull the patch in this week alongside the siblings.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.